package com.itheima.advice;

import com.itheima.mapper.OperateLogMapper;
import com.itheima.pojo.OperateLog;
import com.itheima.utils.MyThreadLocalUtils;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.Map;

/**
 * 这个类承载着我们如何对已有的业务功能进行增强的逻辑
 */
@Component
@Aspect
public class MyAspectLog {
    @Autowired
    private OperateLogMapper operateLogMapper;

    // 为了重复利用同一个切点表达式,我们可以将切点表达式抽取出来,放在一个独立的方法上,使用 @Pointcut承载切点表达式即可
    @Around("execution(* com.itheima.service.*.*(..))")
    public Object totalTime(ProceedingJoinPoint pjp) throws Throwable {
        String name = pjp.getSignature().getName();
        if("login".equals(name)){
            Object o = pjp.proceed();
            return o;
        }
        // 开始写增强的逻辑
        long t1 = System.currentTimeMillis();
        // 让原始方法执行
        Object o = null;
        try {
            // 当目标方法没有返回值或目标方法执行失败的时候,会导致o为null
            o = pjp.proceed();
        } finally {
            long t2 = System.currentTimeMillis();
            long l = t2 - t1;
            Map<String,Object> map = MyThreadLocalUtils.getValue();
            Integer userId = Integer.parseInt(map.get("id").toString());
            // 准备log对象
            OperateLog log = OperateLog.builder()
                    .operateUser(userId)
                    .operateTime(LocalDateTime.now())
                    .className(pjp.getSignature().getDeclaringTypeName())
                    .methodName(name)
                    .methodParams(Arrays.toString(pjp.getArgs()))
                    .returnValue(o==null?"null":o.toString())
                    .costTime(l)
                    .build();

            // 记录日志
            operateLogMapper.insert(log);
        }
        return o;

    }

}
